package com.autonavi.yunda.yunji.core.service.dbfactory;

import com.alibaba.fastjson.JSONObject;
import com.autonavi.yunda.yunji.common.exception.AmapPreconditions;
import com.autonavi.yunda.yunji.core.enums.DBType;
import com.autonavi.yunda.yunji.core.enums.DatasourceType;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.stereotype.Repository;
import org.springframework.util.StringUtils;
import redis.clients.jedis.JedisPoolConfig;

/**
 * redis工厂
 */
@Repository
@Slf4j
public class RedisFactoryService extends AbstractDataSourceFactory<RedisTemplate<Object, Object>> {


    private final RedisTemplate redisTemplate;

    public RedisFactoryService(@Qualifier("redisTemplate") RedisTemplate redisTemplate) {
        super();
        this.redisTemplate = redisTemplate;
    }

    @Override
    public DBType getDbType() {
        return DBType.REDIS;
    }

    /**
     * 生成数据源，并放入容器中
     */
    @Override
    public RedisTemplate<Object, Object> createDataSource(DatasourceType dataSourceType, String dataSourceConfig) {
        JSONObject config = JSONObject.parseObject(dataSourceConfig);
        String host = config.getString("host");
        int port = config.getInteger("port");
        String password = config.getString("password");
        int db = config.getInteger("db");
        AmapPreconditions.checkArgument(StringUtils.hasLength(host));
        AmapPreconditions.checkArgument(StringUtils.hasLength(password));
        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
        jedisPoolConfig.setMaxTotal(1024);
        jedisPoolConfig.setMaxIdle(100);
        jedisPoolConfig.setMinEvictableIdleTimeMillis(50000);
        jedisPoolConfig.setTimeBetweenEvictionRunsMillis(20000);
        jedisPoolConfig.setNumTestsPerEvictionRun(-1);
        jedisPoolConfig.setSoftMinEvictableIdleTimeMillis(10000);
        jedisPoolConfig.setMaxWaitMillis(1000);
        jedisPoolConfig.setTestOnBorrow(true);
        jedisPoolConfig.setTestWhileIdle(true);
        jedisPoolConfig.setTestOnReturn(false);
        jedisPoolConfig.setJmxEnabled(true);
        jedisPoolConfig.setJmxNamePrefix("pool");
        jedisPoolConfig.setBlockWhenExhausted(false);

        JedisConnectionFactory jedisConnectFactory = new JedisConnectionFactory();
        jedisConnectFactory.setPoolConfig(jedisPoolConfig);
        jedisConnectFactory.setHostName(host);
        jedisConnectFactory.setPort(port);
        jedisConnectFactory.setPassword(password);
        jedisConnectFactory.setDatabase(db);
        jedisConnectFactory.afterPropertiesSet();

        RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(jedisConnectFactory);
        StringRedisSerializer serializer = new StringRedisSerializer();
        redisTemplate.setDefaultSerializer(serializer);
        redisTemplate.setKeySerializer(serializer);
        redisTemplate.setValueSerializer(serializer);
        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }

    @Override
    public void close(RedisTemplate<Object, Object> dataSource) {
        if (dataSource == null) {
            return;
        }
        RedisConnectionFactory redisConnectionFactory = redisTemplate.getConnectionFactory();
        if (redisConnectionFactory instanceof LettuceConnectionFactory) {
            ((LettuceConnectionFactory) redisConnectionFactory).destroy();
        } else if (redisConnectionFactory instanceof JedisConnectionFactory) {
            ((JedisConnectionFactory) redisConnectionFactory).destroy();
        }
    }
}
